package com.arpa.wms.service.impl;

import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.arpa.core.web.Result;
import com.arpa.ntocc.common.common.Page;
import com.arpa.ntocc.common.common.cache.PartyCache;
import com.arpa.ntocc.common.common.cache.ShipmentCache;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.CommonUtil;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.wms.cache.BrandCache;
import com.arpa.wms.common.util.UUIDUtil;
import com.arpa.wms.domain.consts.NumConst;
import com.arpa.wms.domain.consts.PropertyConst;
import com.arpa.wms.domain.dto.BrandDTO;
import com.arpa.wms.domain.entity.Brand;
import com.arpa.wms.domain.enums.DeleteFlagEnum;
import com.arpa.wms.domain.enums.StatusEnum;
import com.arpa.wms.domain.vo.BrandVO;
import com.arpa.wms.domain.vo.GoodsVO;
import com.arpa.wms.mapper.BrandMapper;
import com.arpa.wms.mapper.GoodsMapper;
import com.arpa.wms.service.IBrandService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.qimen.api.request.ItemsSynchronizeRequest;
import com.qimen.api.request.SingleitemSynchronizeRequest;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 品牌 服务实现类
 * </p>
 *
 * @author LEO
 * @since 2020-08-03
 */
@Service
@Log4j2
public class BrandServiceImpl extends ServiceImpl<BrandMapper,Brand> implements IBrandService {

    private final PartyCache partyCache;
    private final ShipmentCache shipmentCache;
    private final BrandCache brandCache;
    @Resource
    private GoodsMapper goodsMapper;


    public BrandServiceImpl(PartyCache partyCache,
                            BrandCache brandCache,
                            ShipmentCache shipmentCache ) {
        this.partyCache = partyCache;
        this.brandCache = brandCache;
        this.shipmentCache = shipmentCache;
    }
    private static  final String BRAND_CODE_MANAGE = "同一机构下的编码不能相同！";
    private static  final String BRAND_NAME_MANAGE = "同一机构下的名称不能相同！";

    @Override
    public boolean checkNameOrCode(Brand entity) {

        return false;
    }

    /**
     * 保存
     * @param entity
     * @return
*/
    @Override
    @Transactional(rollbackFor={Exception.class})
    public boolean save(Brand entity) {
        String groupCode = UserUtil.getBranchCode();
        entity.setStatus(StatusEnum.UNACTIVE.getValue());
        if(StrUtil.isBlank(entity.getCode())){
            //用同一个
            entity.setCode(UUIDUtil.getUUID32());
        }
        if(StrUtil.isBlank(entity.getCreatedBy())){
            entity.setCreatedBy(UserUtil.getCode());
            entity.setCreatedName(partyCache.translate(entity.getCreatedBy()));
        }
        entity.setShipmentName(shipmentCache.translate(entity.getShipmentCode()));
        entity.setModifiedBy(UserUtil.getCode());
        entity.setModifiedName(partyCache.translate(entity.getModifiedBy()));
        entity.setGroupCode(UserUtil.getBranchCode());
        BrandDTO dto = new BrandDTO();
        dto.setShipmentName(entity.getShipmentName());
        dto.setName(entity.getName());
        dto.setGroupCode(groupCode);
        BrandVO brandVO = baseMapper.checkNameOrCode(dto);
        if(null != brandVO){
            throw new ServiceException(BRAND_NAME_MANAGE);
        }
        dto.setName("");
        dto.setBrandNumber(entity.getBrandNumber());
        BrandVO brandVO1;
        brandVO1 = baseMapper.checkNameOrCode(dto);
        if(null != brandVO1){
            throw new ServiceException(BRAND_CODE_MANAGE);
        }
        brandCache.flushAllCacheByGroupCode(UserUtil.getBranchCode());
        brandCache.flushAllCacheByShipmentCode(dto.getShipmentCode());

        return super.save(entity);

    }



    /**
     * 根据code更新实体
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor={Exception.class})
    public int updateByCode(Brand entity) {

        //不要传递  entity 参数
        BrandDTO dto = new BrandDTO();
        dto.setShipmentCode(entity.getShipmentCode());
        dto.setName(entity.getName());
        dto.setGroupCode(UserUtil.getBranchCode());
        BrandVO brandVO = baseMapper.checkNameOrCode(dto);
        if(null != brandVO && !brandVO.getCode().equals(entity.getCode())){
            throw new ServiceException(BRAND_NAME_MANAGE);
        }
        dto.setName("");
        dto.setBrandNumber(entity.getBrandNumber());
        dto.setGroupCode(UserUtil.getBranchCode());
        BrandVO brandVO1 = baseMapper.checkNameOrCode(dto);
        if(null != brandVO1 && !brandVO1.getCode().equals(entity.getCode())){
            throw new ServiceException(BRAND_CODE_MANAGE);
        }
        if(StrUtil.isBlank(entity.getModifiedBy())){
            entity.setModifiedBy(UserUtil.getCode());
            entity.setModifiedName(partyCache.translate(entity.getModifiedBy()));
        }

        brandCache.flushCache(entity.getCode());
        return baseMapper.update(entity,new QueryWrapper<Brand>().lambda().eq(Brand::getCode,entity.getCode()).eq(Brand::getGroupCode,UserUtil.getBranchCode()));

    }





    /**
     * 查询列表
     * @param brandDTO
     * @return
     */
    @Override
    public List<BrandVO> queryList(BrandDTO brandDTO){
        //排序字段名需要驼峰转数据库下划线类型字段名
        if(StrUtil.isNotEmpty(brandDTO.getSortField())){
            brandDTO.setSortField(CommonUtil.camel2Underline(brandDTO.getSortField()));
        }
        List<BrandVO> brandVOList = baseMapper.queryList(brandDTO);
        if (IterUtil.isNotEmpty(brandVOList)) {
            brandVOList.forEach(r -> {
                r.setShipmentName(shipmentCache.translate(r.getShipmentCode()));
                StatusEnum enumByValue = StatusEnum.getEnumByValue(r.getStatus());
                if (null != enumByValue) {
                    r.setStatusName(enumByValue.getDesc());
                }
            });
        }

        return brandVOList;
    }


    @Override
    public List<BrandVO> getListByCodes(List<String> codes) {
        return baseMapper.getListByCodes(codes,UserUtil.getBranchCode());
    }

    /**
     * 获取品牌信息
     *
     * @param code 品牌code
     * @return
     */
    @Override
    public Map<String, Object> getByCode(String code,String groupCode) {
        Map<String,Object> brand = brandCache.get(code);
        brand.put(PropertyConst.SHIPMENT_NAME,shipmentCache.translate(MapUtil.getStr(brand, PropertyConst.SHIPMENT_CODE)));
        StatusEnum enumByValue = StatusEnum.getEnumByValue(MapUtil.getStr(brand,"status"));
        if (null != enumByValue) {
            brand.put("statusName",enumByValue.getDesc());
        }
        return brand;
    }

    /**
     * 查询合计,包含总数
     * @param brandDTO
     * @return
     */
    @Override
    public BrandVO queryListSum(BrandDTO brandDTO){
        BrandVO brandVO = baseMapper.queryListSum(brandDTO);
        return brandVO;
    }

    @Override
    public int batchDelete(List<String> list) {

        return baseMapper.batchDelete(list);
    }

    private int updateStatus(List<String> codes,String status){
        int num = 0;
        boolean flag = false;
        if (IterUtil.isNotEmpty(codes)) {
            for (String code : codes) {
                if (status.equals(StatusEnum.ACTIVE.getValue())) {
                    flag = this.update(new UpdateWrapper<Brand>().lambda().set(Brand::getStatus, status).set(Brand::getDeleteFlag, DeleteFlagEnum.NOTDELETE.getCode())
                            .eq(Brand::getCode, code).eq(Brand::getGroupCode, UserUtil.getBranchCode()));
                } else {
                    flag = this.update(new UpdateWrapper<Brand>().lambda().set(Brand::getStatus, status)
                            .eq(Brand::getCode, code).eq(Brand::getGroupCode, UserUtil.getBranchCode()));
                }
                if (flag) {
                    brandCache.flushCache(code);
                    num++;
                }
            }
        }
        return num;

    }

    @Override
    public Map<String,Object> batchUpdateStatus(List<String> codes,String status) {
        Map<String,Object> result;
        result = new HashMap<>();
        int num = 0;
        if(status.equals(StatusEnum.UNACTIVE.getValue())){
            List<GoodsVO> goodsVOS = goodsMapper.queryByBrandCode(codes,UserUtil.getBranchCode());
            List<String> temp = goodsVOS.stream().map(GoodsVO::getBrandCode).collect(Collectors.toList());
            //占用的code
            List<String> usedList = temp.stream().distinct().collect(Collectors.toList());
            if(IterUtil.isNotEmpty(usedList)){
                List<String> useName = usedList.stream().map(brandCache::translate).collect(Collectors.toList());
                result.put("useName",useName);
            }

            //可操作的code
            List<String> usefulCodes = codes.stream().filter(item -> !usedList.contains(item)).collect(Collectors.toList());
            if(IterUtil.isNotEmpty(usefulCodes)){
                num = updateStatus(usefulCodes, status);
            }
        }else {
            num = updateStatus(codes, status);
        }
        result.put(PropertyConst.SUCCESS,num);
        return result;
        }

    /**
     * 获取货主商品品牌列表
     *
     * @param shipmentCode
     * @return
     */
    @Override
    public List<Map<String, Object>> findByShipmentCode(String shipmentCode) {
        List<Map<String, Object>> brands = brandCache.getAllByShipmentCode(shipmentCode);
        if (IterUtil.isNotEmpty(brands)) {
            brands = brands.stream().filter(r -> NumConst.NUM_ZERO.toString().equals(r.get("status"))).collect(Collectors.toList());
        }
        return brands;
    }


    /**
     * 通过code删除单位
     *
     * @param codes
     */
    @Override
    public Map<String,Object> removeByCode(List<String> codes) {
        Map<String,Object> result = new HashMap<>();
        List<BrandVO> listByCodes = getListByCodes(codes);
        List<String> notDelete = listByCodes.stream().filter(info -> info.getDeleteFlag().equals(DeleteFlagEnum.NOTDELETE.getCode().toString())).map(r -> {
            return r.getCode();
        }).collect(Collectors.toList());
        if(IterUtil.isNotEmpty(notDelete)){
            List<String> notDeleteNames = notDelete.stream().map(code -> {
                return brandCache.translate(code);
            }).collect(Collectors.toList());
            result.put("notDelete",notDeleteNames);
        }
        List<String> canDelete = codes.stream().filter(code -> !notDelete.contains(code)).collect(Collectors.toList());
        int delete = 0;
        if(IterUtil.isNotEmpty(canDelete)){
            delete = baseMapper.delete(new QueryWrapper<Brand>().lambda().in(Brand::getCode, canDelete).eq(Brand::getGroupCode,UserUtil.getBranchCode()));
            if(delete > 0){
                for (String code:canDelete) {
                    brandCache.flushCache(code);
                }
            }
        }
        result.put(PropertyConst.SUCCESS,delete);
        return result;
    }

    /**
     * 批量同步商品时，根据操作类型判断是插入还是更新
     *
     * @param request
     * @param shipmentName
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void batchGoodsBrandSave(ItemsSynchronizeRequest request, String shipmentName){
        String shipmentPartyCode = request.getOwnerCode();
        List<ItemsSynchronizeRequest.Item> items = request.getItems();
        List<Brand> brandList = Lists.newArrayList();
        for (ItemsSynchronizeRequest.Item item : items) {
            String brandCode = item.getBrandCode();
            //商品品牌为空时，不需要添加
            if (StrUtil.isEmpty(brandCode)) {
                continue;
            }
            Brand originBrand = this.getOne(new QueryWrapper<Brand>().lambda().eq(Brand::getCode, brandCode).eq(Brand::getDeleted, NumConst.NUM_ZERO).eq(Brand::getGroupCode,UserUtil.getBranchCode()));
            if (ObjectUtil.isNull(originBrand)) {
                Brand brand = new Brand();
                brand.setCode(brandCode);
                brand.setShipmentCode(shipmentPartyCode);
                brand.setShipmentName(shipmentName);
                brand.setName(item.getBrandName());
                brand.setGmtCreated(LocalDateTime.now());
                brand.setCreatedBy(UserUtil.getCode());
                brand.setCreatedName(partyCache.translate(UserUtil.getCode()));
                brandList.add(brand);
            }
        }
        // 拼接sql，批量执行新增操作
        importBatchSave(brandList);
    }

    /**
     * 同步单个商品品牌
     *
     * @param request
     * @param shipmentName
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void singleGoodsBrandSave(SingleitemSynchronizeRequest request, String shipmentName){
        log.info("《《《《《 同步商品品牌开始 3》》》》》");
        String shipmentPartyCode = request.getOwnerCode();
        String brandCode = request.getItem().getBrandCode();
        //品牌代码为空时，不添加品牌
        if (StrUtil.isEmpty(brandCode)) {
            return;
        }
        Brand originBrand = this.getOne(new QueryWrapper<Brand>().lambda().eq(Brand::getCode, brandCode).eq(Brand::getDeleted, NumConst.NUM_ZERO).eq(Brand::getGroupCode,UserUtil.getBranchCode()));
        if (ObjectUtil.isNull(originBrand)) {
            Brand brand = new Brand();
            brand.setCode(brandCode);
            brand.setShipmentCode(shipmentPartyCode);
            brand.setShipmentName(shipmentName);
            brand.setName(request.getItem().getBrandName());
            brand.setGmtCreated(LocalDateTime.now());
            brand.setCreatedBy(UserUtil.getCode());
            brand.setCreatedName(partyCache.translate(UserUtil.getCode()));
            //品牌编码默认不为空，先给其如下默认值
            brand.setBrandNumber("奇门default品牌编码");
            this.save(brand);
        }
        log.info("《《《《《 同步商品品牌结束 3》》》》》");
    }

    /**
     * 同步-批量保存操作
     * @param brandList
     * @return
     */
    private int importBatchSave(List<Brand> brandList) {
        StringBuilder data = new StringBuilder();
        data.append("INSERT INTO `base_brand`(`id`, `code`,`group_code`, `shipment_code`, `shipment_name`, `name`, "
                + " `gmt_created`, `created_by`,`created_name`) values ");
        String sql = brandList.stream().map(e -> makeInsertValueStr(e)).collect(Collectors.joining(","));
        data.append(sql);
        return this.baseMapper.execSql(data.toString());
    }

    /**
     * 同步-批量插入生成sql
     * @param brand
     * @return
     */
    private StringBuilder makeInsertValueStr(final Brand brand) {
        StringBuilder data = new StringBuilder();
        data.append("(");
        // id
        data.append("default, ");
        // code
        data.append("'").append(brand.getCode()).append("', ");
        // group_code
        data.append("'").append(UserUtil.getBranchCode()).append("', ");
        // shipment_code
        data.append("'").append(ObjectUtil.defaultIfNull(brand.getShipmentCode(), StrUtil.EMPTY)).append("', ");
        // shipment_name
        data.append("'").append(ObjectUtil.defaultIfNull(brand.getShipmentName(), StrUtil.EMPTY)).append("', ");
        // name
        data.append("'").append(ObjectUtil.defaultIfNull(brand.getName(), StrUtil.EMPTY)).append("', ");
        // gmt_created
        data.append("'").append(ObjectUtil.defaultIfNull(brand.getGmtCreated(), LocalDateTime.now())).append("', ");
        // created_by
        data.append("'").append(ObjectUtil.defaultIfNull(brand.getCreatedBy(), StrUtil.EMPTY)).append("', ");
        // created_name
        data.append("'").append(ObjectUtil.defaultIfNull(brand.getCreatedName(), StrUtil.EMPTY)).append("' ");
        data.append(")");
        return data;
    }

    public  static Result getResult(BrandDTO brandDTO, IBrandService iBrandService){
        BrandVO brandVOSum=  iBrandService.queryListSum(brandDTO);
        List<BrandVO> brandVOList= iBrandService.queryList(brandDTO);

        Page returnPage=new Page(brandDTO.getPageNum(),brandDTO.getPageSize());
        returnPage.setRecords(brandVOList);
        returnPage.setTotal(brandVOSum.getTotal());
        returnPage.setSumObject(brandVOSum);
        return Result.ok().data(returnPage);
    }
}
